package com.sxbbc.common.core.service.system.pay;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sxbbc.common.basics.files.RestUploadFileInfo;
import com.sxbbc.common.basics.files.UploadUtils;
import com.sxbbc.common.core.dto.jz.FarmLogisticsOrderPayVo;
import com.sxbbc.common.core.dto.jz.FarmOrderPayVo;
import com.sxbbc.common.core.entity.jz.*;
import com.sxbbc.common.core.enums.*;
import com.sxbbc.common.core.mapper.jz.BankDetailMapper;
import com.sxbbc.common.core.mapper.jz.CReceivedAddrMapper;
import com.sxbbc.common.core.mapper.jz.ChickenOrderMapper;
import com.sxbbc.common.core.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.common.basics.enums.ServiceEnums;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.login.LoginDto;
import com.sxbbc.common.basics.service.redis.RedisUtilsService;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.basics.utils.date.DateUtil;
import com.sxbbc.common.basics.utils.encrypts.pwd.Encode;
import com.sxbbc.common.basics.utils.statics.StaticUtils;
import com.sxbbc.common.core.enums.redis.RedisExpiredEnums;
import com.sxbbc.common.core.service.system.login.LoginTokenService;
import com.sxbbc.common.core.service.system.pay.dto.CartpayDto;
import com.sxbbc.common.core.service.system.pay.dto.SettleDetailDto;
import com.sxbbc.common.core.service.system.pay.dto.SettleDto;

/**
 * 处理订单信息
 *
 * @author arno
 */
@Service
public class PayOrderService {
    @Autowired
    private IBExpConfigService ibExpConfigService;
    @Autowired
    private CReceivedAddrMapper cReceivedAddrMapper;
    @Autowired
    private ICAccountService icAccountService;
    @Autowired
    private IAddressService iAddressService;
    @Autowired
    private IChickenOrderService iChickenOrderService;
    @Autowired
    private LoginTokenService loginTokenService;
    @Autowired
    private ChickenOrderMapper chickenOrderMapper;
    @Autowired
    private ICReceivedAddrService icReceivedAddrService;
    @Autowired
    private IProcMainService iProcMainService;
    @Autowired
    private IProSkuDetailService iProSkuDetailService;
    @Autowired
    private BBusinessService bBusinessService;
    @Autowired
    private ExpService expService;
    @Autowired
    private RedisUtilsService redisUtilsService;
    @Autowired
    private IOrderSeckillConfigService iOrderSeckillConfigService;
    @Autowired
    private IProGroupConfigService iProGroupConfigService;
    @Autowired
    private ICShoppingCartService icShoppingCartService;
    @Autowired
    private ICCustomerService icCustomerService;
    @Autowired
    private IInfoShoppingService iInfoShoppingService;
    @Autowired
    private IOrderMainService iOrderMainService;
    @Autowired
    private IOrderDetailService iOrderDetailService;
    @Autowired
    private IOrderExpDetailService iOrderExpDetailService;
    @Autowired
    private IActivitySeckillDetailService iActivitySeckillDetailService;
    @Autowired
    private ICPayLogService icPayLogService;
    @Autowired
    private PayService payService;
    @Autowired
    private IOrderConfigGroupService iOrderConfigGroupService;
    @Autowired
    private IWWarehouseService iwWarehouseService;
    @Autowired
    private ICCustomerAuthenService customerAuthenService;
    @Autowired
    private BankDetailMapper bankDetailMapper;
    @Autowired
    private IChickenLevelService iChickenLevelService;
    @Autowired
    private IChickenCouponService iChickenCouponService;

    /***
     *
     * 这个业务层表示为订单 去支付 跳转结算页面，单笔。多笔显示
     * 选择支付方式之后，下单
     * 业务流程表示为：1：根据单订单获取结算信息，2根据多订单获取结算信息
     * 3.获取支付方式列表 提供给APP，或者他们固定也行。
     * 4.开始下单  只需要将结算信息中的交易单号 支付方式传过来进行订单处理，库存是下单的时候直接扣除，
     * 订单保存了有效期，当订单失效的时候redis会监听那个订单时间到了还没有支付，这个时候我们会处理他的库存返还。
     * 注意 库存扣除 如果是秒杀产品扣除秒杀库存不会去操作商品的库存，价格都是统一在一个方法计算单价，根据目前的团购活动，或者秒杀活动计算商品单价
     *
     *
     *
     */

    /*************************************订单去支付显示数据*******************************/

    /**
     * 获取支付方式
     *
     * @return
     */
    public RestResponse queryPayType() {
        PayTypeEnums[] enums = PayTypeEnums.values();
        return GetRest.getSuccess("成功", enums);
    }

    /**
     * 获取单笔支付信息
     *
     * @param token     用户token
     * @param addrId    收货地址id
     * @param proCode   产品编号
     * @param skuId     产品详情id，也就是选择到对应组合规格数据的id
     * @param qty       数量
     * @param orderType 交易类型 1普通  3拼团
     * @param groupCode 加入团购编号
     * @return 返回 status 状态，data数据结构，flag交易单号
     */
    public RestResponse getSingleOrderPayData(String token, Integer addrId, String proCode, Integer skuId, Integer qty,
                                              Integer orderType, String groupCode) {
        if (!OrderTypeEnums.isOrderType(orderType)) {
            return GetRest.getFail("参数错误");
        }
        if (StringUtils.isEmpty(proCode)) {
            return GetRest.getFail("商品编码错误");
        }
        if (skuId == null) {
            return GetRest.getFail("请选择规格");
        }
        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        //1.获取收货地址
        CReceivedAddr receivedAddr = null;
        if (addrId == null) {
            //获取默认地址
            receivedAddr = icReceivedAddrService.getDefaultAddr(dto.getCid());
        } else {
            receivedAddr = icReceivedAddrService.getById(addrId);
        }
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        BigDecimal totalPoint = BigDecimal.ZERO;
        //1.校验商品是否可以下单
        ProcMain main = iProcMainService.selectOneByProCode(proCode);
        if (main == null || !calcuUtils.isEquals(ProductStatusEnums.SHELVES.getId(), main.getStatus())) {
            return GetRest.getFail("宝贝不存在或已下架~");
        }
        ProSkuDetail skuDetail = iProSkuDetailService.getById(skuId);
        if (skuDetail == null || !calcuUtils.isEquals(StaticUtils.STATUS_YES, skuDetail.getStatus())) {
            return GetRest.getFail("宝贝不存在或已下架~");
        }
        //组装数据
        //生成交易单号
        String payCode = calcuUtils.getOrderCode("OS");
        SettleDto settleDto = new SettleDto();
        //组装店铺信息
        settleDto.setBid(main.getBid());
        settleDto.setBname("平台自营");
        settleDto.setPaycode(payCode);
        settleDto.setGroupcode(groupCode);
        if (main.getBid() != null) {
            BBusiness bBusiness = bBusinessService.getById(main.getBid());
            settleDto.setBname(bBusiness.getNickNameOn());
            if (CalcuUtils.getInstance().isEquals(BusinessTypeEnums.OWN_BUSINESS.getId(), bBusiness.getBType())) {
                settleDto.setBTypeName(BusinessTypeEnums.getName(bBusiness.getBType()));
            }
            settleDto.setBType(bBusiness.getBType());
        }
        //获取仓库id

        settleDto.setWarehouseId(null);
        settleDto.setOrderType(orderType);
        settleDto.setReceivedAddr(receivedAddr);
        //组装商品信息
        List<SettleDetailDto> detailDtos = new ArrayList<>();
        SettleDetailDto detailDto = new SettleDetailDto();
        detailDto.setPid(main.getId());
        detailDto.setPname(main.getProName());
        detailDto.setLabel(main.getLabel());
        detailDto.setQty(qty);
        detailDto.setSkuid(skuId);
        detailDto.setSkuname(skuDetail.getSpecName());
        detailDto.setProcode(proCode);
        detailDto.setExpid(main.getExpId());
        detailDto.setPurl(main.getProUrl());
        detailDto.setUnit(main.getProUnit());
        detailDto.setValuationType(main.getValuationType());
        detailDto.setWeightUnit(main.getWeightUnit());
        detailDto.setProType(main.getProType());
        detailDto.setRefundFlag(main.getIsRefund());
        detailDto.setPoint(skuDetail.getPoint());
        totalPoint = CalcuUtils.getInstance().add(totalPoint, CalcuUtils.getInstance().mul(new BigDecimal(qty), skuDetail.getPoint(), 2), 2);

        //如果记重 保存重量
        if (CalcuUtils.getInstance().isEquals(ValuationTypeEnums.WEIGHT.getId(), main.getValuationType())) {
            BigDecimal weight = CalcuUtils.getInstance().mul(main.getWeightUnit(), new BigDecimal(qty), 2);
            detailDto.setWeight(weight);
        }
        detailDtos.add(detailDto);
        settleDto.setDetailDtos(detailDtos);
        //设置订单价格
        settleDto = getOrderMoney(dto.getCid(), settleDto, receivedAddr);
        settleDto.setPoint(totalPoint);
        //设置订单 存在有效期 5分钟
        redisUtilsService.setKey(RedisExpiredEnums.ORDER_SETTLE_BUY.getKey() + payCode, JSONObject.toJSONString(settleDto), RedisExpiredEnums.ORDER_SETTLE_BUY.getSecond());
        return GetRest.getSuccess("成功", settleDto, payCode);
    }

    /**
     * 获取购物车支付信息
     *
     * @param token   用户token
     * @param addrid  收货地址id
     * @param cartids 购物车选中id数组
     * @return 返回 status 状态，data数据结构，flag交易单号
     */
    public RestResponse getCartOrderPayData(String token, Integer addrid, List<Integer> cartids, boolean onOff, Integer bid) {
        if (cartids == null || cartids.size() < 1) {
            return GetRest.getFail("至少勾选一个产品~");
        }
        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        //1.获取收货地址
        CReceivedAddr receivedAddr = null;
        String businessAddress = null;
        if (onOff) {
            BBusiness business = bBusinessService.getById(bid);
            if (business != null) {
                String addrName = iAddressService.getAddrName(business.getProId(), business.getCityId(), business.getAreaId());
                businessAddress = addrName.concat(business.getAddressDetail());
            }
        } else {
            if (addrid == null) {
                //获取默认地址
                receivedAddr = icReceivedAddrService.getDefaultAddr(dto.getCid());
            } else {
                receivedAddr = icReceivedAddrService.getById(addrid);
            }
        }
        List<SettleDto> dtos = new ArrayList<SettleDto>();
        //1根据店铺分组
        //生成交易单号
        String payCode = CalcuUtils.getInstance().getOrderCode("OM");
        List<Integer> bidList = icShoppingCartService.queryMoreBid(dto.getCid(), cartids);
        for (Integer b : bidList) {
            SettleDto settleDto = new SettleDto();
            //组装店铺信息
            settleDto.setBid(b);
            settleDto.setBname("平台自营");
            settleDto.setPaycode(payCode);
            settleDto.setBTypeName("");
            if (b != null) {
                BBusiness bBusiness = bBusinessService.getById(b);
                if (CalcuUtils.getInstance().isEquals(bBusiness.getBType(), BusinessTypeEnums.OWN_BUSINESS.getId())) {
                    settleDto.setBname(bBusiness.getNickNameOn());
                } else {
                    settleDto.setBname(bBusiness.getNickName());
                }
                settleDto.setBTypeName(BusinessTypeEnums.getName(bBusiness.getBType()));
                settleDto.setBType(bBusiness.getBType());
            }
            settleDto.setWarehouseId(null);
            //2.根据店铺获取 产品信息
            //组装商品信息
            List<SettleDetailDto> detailDtos = new ArrayList<>();
            QueryWrapper<CShoppingCart> wrapper = new QueryWrapper<>();
            wrapper.eq("cid", dto.getCid());
            wrapper.eq("bid", b);
            wrapper.gt("qty", 0);
            wrapper.in("id", cartids);
            List<CShoppingCart> list = icShoppingCartService.list(wrapper);
            BigDecimal totalPoint = BigDecimal.ZERO;
            for (CShoppingCart c : list) {
                SettleDetailDto detailDto = new SettleDetailDto();
                detailDto.setPid(c.getProId());
                detailDto.setPname(c.getProName());
                detailDto.setQty(c.getQty());
                detailDto.setSkuid(c.getSkuId());
                detailDto.setProcode(c.getProCode());
                ProcMain main = iProcMainService.selectOneByProCode(c.getProCode());
                if (main == null || !CalcuUtils.getInstance().isEquals(ProductStatusEnums.SHELVES.getId(), main.getStatus())) {
                    return GetRest.getFail("宝贝不存在或已下架~");
                }
                ProSkuDetail skuDetail = iProSkuDetailService.getById(c.getSkuId());
                if (skuDetail == null || !CalcuUtils.getInstance().isEquals(StaticUtils.STATUS_YES, skuDetail.getStatus())) {
                    return GetRest.getFail("宝贝不存在或已下架~");
                }
                detailDto.setSkuname(skuDetail.getSpecName());
                detailDto.setPurl(main.getProUrl());
                detailDto.setUnit(main.getProUnit());
                detailDto.setLabel(main.getLabel());
                detailDto.setPoint(skuDetail.getPoint());
                totalPoint = CalcuUtils.getInstance().add(totalPoint, CalcuUtils.getInstance().mul(new BigDecimal(c.getQty()), skuDetail.getPoint(), 2), 2);
                detailDto.setExpid(main.getExpId());
                detailDto.setValuationType(main.getValuationType());
                detailDto.setWeightUnit(main.getWeightUnit());
                detailDto.setProType(main.getProType());
                detailDto.setRefundFlag(main.getIsRefund());
                //如果记重 保存重量
                if (CalcuUtils.getInstance().isEquals(ValuationTypeEnums.WEIGHT.getId(), main.getValuationType())) {
                    BigDecimal weight = CalcuUtils.getInstance().mul(main.getWeightUnit(), new BigDecimal(c.getQty()), 2);
                    detailDto.setWeight(weight);
                }
                detailDtos.add(detailDto);
            }
            settleDto.setDetailDtos(detailDtos);
            settleDto.setPoint(totalPoint);
            //核算订单价格
            settleDto = getOrderMoney(dto.getCid(), settleDto, receivedAddr);
            settleDto.setPoint(totalPoint);
            if (onOff) {
                settleDto.setOrderType(OrderTypeEnums.OFFLINE.getId()); //如果为线下入口多商品购买则标记为线下订单
            } else {
                settleDto.setOrderType(OrderTypeEnums.NORMAL.getId());
            }
            dtos.add(settleDto);
        }
        CartpayDto cartpayDto = new CartpayDto();
        cartpayDto.setList(dtos);
        cartpayDto.setAddr(receivedAddr);
        cartpayDto.setBusinessAddress(businessAddress);

        //将结果集放入缓存
        //设置订单 存在有效期 5分钟
        redisUtilsService.setKey(RedisExpiredEnums.ORDER_SETTLE_BUY.getKey() + payCode, JSONObject.toJSONString(cartpayDto), RedisExpiredEnums.ORDER_SETTLE_BUY.getSecond());
        return GetRest.getSuccess("成功", cartpayDto, payCode);
    }

    /**
     * 计算订单金额
     *
     * @param settleDto 订单金额
     * @param addr      收货地址
     */
    private SettleDto getOrderMoney(Integer cid, SettleDto settleDto, CReceivedAddr addr) {
        //货物总额=货物单价*数量总额
        BigDecimal goodsMoney = BigDecimal.ZERO;
        //实际金额=货物金额-各类折扣-积分抵扣 不含运费
        BigDecimal realMoney = BigDecimal.ZERO;
        //运费
        BigDecimal expMoney = BigDecimal.ZERO;
        //需要支付金额=实际支付金额+运费
        BigDecimal payMoney = BigDecimal.ZERO;
        //折扣金额=会员等级折扣+商品折扣
        BigDecimal discountMoney = BigDecimal.ZERO;
        //优惠券金额
        BigDecimal couponMoney = BigDecimal.ZERO;
        //其他优惠金额
        BigDecimal otherMoney = BigDecimal.ZERO;
        // 积分
        //BigDecimal point = BigDecimal.ZERO;
        //总数量
        Integer totalNum = 0;
        //循环商品
        List<BigDecimal> expList = new ArrayList<>();
        Set<String> label = new HashSet<>();
        for (SettleDetailDto d : settleDto.getDetailDtos()) {
            ProSkuDetail detail = iProSkuDetailService.getById(d.getSkuid());
            if (detail == null || !CalcuUtils.getInstance().isEquals(StaticUtils.STATUS_YES, detail.getStatus())) {
                throw new ThrowJsonException("宝贝规格不存在或已下架~");
            }
            totalNum += d.getQty();
            //设置订单价格
            BigDecimal price = getPriceFunction(cid, detail, d.getQty(), d);
            d.setPrice(price);
            d.setCostPrice(detail.getCost());
            d.setSkuname(d.getSkuname());
            //设置拼团信息
            ProGroupConfig config = iProGroupConfigService.selectGroupProduct(d.getProcode());
            if (config != null) {
                d.setGroupNum(config.getNum());
                d.setGroupTime(config.getTimes());
                d.setOverTime(config.getOverTime());
            }
            //计算货物价格
            BigDecimal goodMoney = CalcuUtils.getInstance().mul(d.getPrice(), new BigDecimal(d.getQty()), 2);
            //设置货物金额
            d.setGoodmoney(goodMoney);
            //累积商品货物金额
            goodsMoney = CalcuUtils.getInstance().add(goodsMoney, goodMoney, 2);
            //计算商品运费
            BigDecimal exp = expService.getExp(addr, d.getExpid(), goodMoney, d.getQty(), d.getWeight(), d.getValuationType());
            expList.add(exp);
            label.add(d.getLabel());
        }
        //获取当前订单最大运费
        expMoney = expService.getMaxExp(expList);
        //设置实际金额
        realMoney = goodsMoney;
        payMoney = CalcuUtils.getInstance().add(realMoney, expMoney, 2);
        settleDto.setGoodsMoney(goodsMoney);
        settleDto.setRealMoney(realMoney);
        if (label != null && label.size() > 0) {
            settleDto.setLabel(StringUtils.join(label, ","));
        }
        settleDto.setPayMoney(payMoney);
        settleDto.setDiscountMoney(discountMoney);
        settleDto.setCouponMoney(couponMoney);
        settleDto.setOtherMoney(otherMoney);
        settleDto.setTotalNum(totalNum);
        settleDto.setExpMoney(expMoney);
        //settleDto.setPoint(point);
        return settleDto;
    }

    /**
     * 获取商品单价 并且校验库存
     *
     * @return
     */
    private BigDecimal getPriceFunction(Integer cid, ProSkuDetail detail,
                                        Integer qty, SettleDetailDto d) {
        DateUtil dateUtil = DateUtil.getInstance();
        BigDecimal price = detail.getPrice();

        //不是团购的情况下可以享受到 秒杀价
        String result = redisUtilsService.getKey(RedisExpiredEnums.SECKILL_PRO.getKey() + detail.getId());
        if (!StringUtils.isEmpty(result)) {
            long currentTime = dateUtil.currentTimeMillis();
            ActivitySeckillDetail activitySeckillDetail = JSONObject.parseObject(result, ActivitySeckillDetail.class);
            if (currentTime >= activitySeckillDetail.getBeginTime().getTime()
                    && currentTime < activitySeckillDetail.getOverTime().getTime()) {
                //查询秒杀是否有效
                int subQty = activitySeckillDetail.getTotalNum() - activitySeckillDetail.getBuyNum();
                if (qty <= subQty) {
                    if (activitySeckillDetail.getLimitNum() > 0) {
                        //计算当前秒杀产品已经购买数量
                        OrderSeckillConfig config = new OrderSeckillConfig();
                        config.setCid(cid);
                        config.setSkid(activitySeckillDetail.getSeckillId());
                        config.setSkDetailid(activitySeckillDetail.getId());
                        int hasBut = iOrderSeckillConfigService.getBuyNum(config);
                        if (hasBut > activitySeckillDetail.getLimitNum() - qty) {
                            throw new ThrowJsonException("当前活动产品已达购买上限");
                        }
                    }

                    price = activitySeckillDetail.getSeckillPrice();
                    //d.setActivitySign(ActivitySignEnums.SECKILL.getName());
                    //d.setLabel(OrderLabelEnums.SPIKE.getName());

                    //设置秒杀对象
                    OrderSeckillConfig orderSeckillConfig = new OrderSeckillConfig();
                    orderSeckillConfig.setCid(cid);
                    orderSeckillConfig.setOldprice(detail.getPrice());
                    orderSeckillConfig.setPrice(price);
                    orderSeckillConfig.setQty(qty);
                    orderSeckillConfig.setSkid(activitySeckillDetail.getSeckillId());
                    orderSeckillConfig.setSkDetailid(activitySeckillDetail.getId());
                    d.setOrderSeckillConfig(orderSeckillConfig);
                } else {
                    throw new ThrowJsonException("当前活动产品库存仅剩:" + subQty);
                }
            }
        } else {
            //2.校验库存
            if (qty > detail.getQty()) {
                throw new ThrowJsonException("宝贝规格库存不足~");
            }
        }

        return price;
    }

    /*****************支付****************/

    /**
     * 处理订单去支付（线上、线下订单）
     *
     * @param payCode     交易单号
     * @param token
     * @param payWord     支付密码
     * @param payType     支付方式
     * @param remark      订单备注
     * @param payChannel  支付来源渠道 见枚举
     * @param fromChannel 订单渠道 见枚举
     * @param type        支付类型 1单笔 2多笔
     * @return
     */
    public RestResponse handlePayOrder(String payCode, String token, String payWord, Integer payType,
                                       String remark, Integer payChannel, Integer fromChannel, Integer type) {
        if (payType == null) {
            return GetRest.getFail("请选择支付方式");
        }
        if (type == null) {
            return GetRest.getFail("参数错误");
        }
        QueryWrapper<OrderMain> orderWrapper = new QueryWrapper<>();
        orderWrapper.eq("pay_code", payCode);
        int countOrder = iOrderMainService.count(orderWrapper);
        if (countOrder > 0) {
            return GetRest.getFail("交易记录已存在");
        }
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), payType)) {
            if (StringUtils.isBlank(payWord)) {
                return GetRest.getFail("请填写交易密码");
            }
        }
        //1.校验用户信息
        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        CCustomer cCustomer = icCustomerService.getById(dto.getCid());
        if (cCustomer == null) {
            return GetRest.getFail("用户不存在或被冻结");
        } else if (calcuUtils.isEquals(StaticUtils.STATUS_NO, cCustomer.getStatus())) {
            String desc = icCustomerService.checkFrezeeCustomer(UserFreezeEnums.CUSTOMER_PAY.getId(), payType);
            if (desc.length() > 0) {
                return GetRest.getFail(desc);
            }
        }

        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), payType)) {
            if (!calcuUtils.isEquals(cCustomer.getAuthen(), StaticUtils.STATUS_YES)) {
                return GetRest.getFail("请先进行身份认证", null, "2");
            } else {
                QueryWrapper<CCustomerAuthen> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("cid", dto.getCid());
                CCustomerAuthen authen = customerAuthenService.getOne(queryWrapper);
                if (authen == null) {
                    return GetRest.getFail("请求错误，错误代码0000");
                }
            }
        }

        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), payType)
                || calcuUtils.isEquals(PayTypeEnums.PAY_POINT.getId(), payType)) {
            if (StringUtils.isEmpty(cCustomer.getPayWord())) {
                return GetRest.getFail("您还未设置支付密码,请前往设置~", null, "1");
            }
            String pwd = Encode.md5Encode(payWord);
            if (!pwd.equals(cCustomer.getPayWord())) {
                return GetRest.getFail("支付密码不正确");
            }
        }
        //进入下单流程
        BigDecimal payMoney = BigDecimal.ZERO;
        BigDecimal point = BigDecimal.ZERO;
        Integer onOffFlag = BusinessScopeEnums.ONLINE.getId(); //默认为线上订单
        switch (type) {
            /**
             * 单笔订单去支付 StaticUtils.order_single_pay
             */
            case 1:
                String singleStr = redisUtilsService.getKey(RedisExpiredEnums.ORDER_SETTLE_BUY.getKey() + payCode);
                if (StringUtils.isEmpty(singleStr)) {
                    return GetRest.getFail("您的支付已过期,请重新下单");
                }
                SettleDto settleDto = JSONObject.parseObject(singleStr, SettleDto.class);
                if (settleDto.getReceivedAddr() == null) {
                    return GetRest.getFail("请选择收货地址");
                }
                handleSingleOrderPay(settleDto, dto.getCid(), payCode, token, payWord, payType, remark, fromChannel, payChannel);
                // 支付资金信息
                payMoney = settleDto.getPayMoney();
                point = settleDto.getPoint();
                break;
            /**
             * 多订单支付 StaticUtils.order_more_pay
             * 该种情况下有两种，一种为线上自营订单购买，走物流发货，一种为线下订单购买，用户自提
             */
            case 2:
                String moreStr = redisUtilsService.getKey(RedisExpiredEnums.ORDER_SETTLE_BUY.getKey() + payCode);
                if (StringUtils.isEmpty(moreStr)) {
                    return GetRest.getFail("您的支付已过期,请重新下单");
                }
                CartpayDto cartpayDto = JSONObject.parseObject(moreStr, CartpayDto.class);
                if (StringUtils.isNotBlank(cartpayDto.getBusinessAddress())) {
                    onOffFlag = BusinessScopeEnums.OFFLINE.getId();  //线下订单
                }

                if (calcuUtils.isEquals(onOffFlag, BusinessScopeEnums.ONLINE.getId()) && cartpayDto.getAddr() == null) {
                    return GetRest.getFail("请选择收货地址");
                }
                // 处理多订单备注
                List<SettleDto> dtos = cartpayDto.getList();
                String[] remarks = new String[dtos.size()];
                if (!StringUtils.isBlank(remark)) {
                    remark = remark + " ";
                    remarks = remark.split("&");
                }
                for (int i = 0; i < dtos.size(); i++) {
                    SettleDto mSettleDto = dtos.get(i);
                    if (calcuUtils.isEquals(onOffFlag, BusinessScopeEnums.ONLINE.getId())) {
                        mSettleDto.setReceivedAddr(cartpayDto.getAddr());

                    } else if (calcuUtils.isEquals(onOffFlag, BusinessScopeEnums.OFFLINE.getId())) {
                        mSettleDto.setBusinessAddress(cartpayDto.getBusinessAddress());
                    }
                    handleSingleOrderPay(mSettleDto, dto.getCid(), payCode, token, payWord, payType, remarks[i], fromChannel, payChannel);
                    // 支付资金信息 
                    payMoney = calcuUtils.add(payMoney, mSettleDto.getPayMoney(), 2);
                    point = calcuUtils.add(point, mSettleDto.getPoint(), 2);
                    // 多商品——删除购物车信息
                    List<SettleDetailDto> detailDtos = mSettleDto.getDetailDtos();
                    for (SettleDetailDto d : detailDtos) {
                        if (detailDtos.size() >= 1) {
                            QueryWrapper<CShoppingCart> cartWrapper = new QueryWrapper<CShoppingCart>();
                            cartWrapper.eq("cid", dto.getCid()).eq("pro_id", d.getPid()).eq("pro_code", d.getProcode()).eq("sku_id", d.getSkuid());
                            CShoppingCart cart = icShoppingCartService.getOne(cartWrapper);
                            if (cart != null) {
                                icShoppingCartService.removeById(cart.getId());
                            }
                        }
                    }
                }
                break;
            default:
                return GetRest.getFail("参数错误");
        }
        if (payMoney.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ThrowJsonException("支付金额不得小于0");
        }
        CPayLog log = new CPayLog();
        log.setCid(dto.getCid());
        log.setPayCode(payCode);
        log.setPayMoney(payMoney);
        log.setPoint(point);
        if (calcuUtils.isEquals(onOffFlag, BusinessScopeEnums.ONLINE.getId())) {
            log.setServiceType(ServiceEnums.ORDER.getId());
        } else if (calcuUtils.isEquals(onOffFlag, BusinessScopeEnums.OFFLINE.getId())) {
            log.setServiceType(ServiceEnums.OFFLINE_ORDER.getId());
        }
        log.setPayChannel(payChannel);
        log.setPayType(payType);
        if (calcuUtils.isEquals(PayChannlEnums.WX_PUBLIC.getId(), payChannel)) {
            if (StringUtils.isEmpty(cCustomer.getOpenidWx())) {
                throw new ThrowJsonException("OPENID IS NULL");
            }
            log.setOpenId(cCustomer.getOpenidWx());
        } else {
            if (calcuUtils.isEquals(PayChannlEnums.WX_PROGRAM.getId(), payChannel)) {
                if (StringUtils.isEmpty(cCustomer.getOpenidProgram())) {
                    throw new ThrowJsonException("OPENID IS NULL");
                }
                log.setOpenId(cCustomer.getOpenidProgram());
            }
        }
        boolean flag = icPayLogService.save(log);
        if (!flag) {
            throw new ThrowJsonException("生成支付记录失败");
        }
        //支付记录存在之后开始处理订单签名
        return payService.handleSign(log);
    }

    /**
     * 处理单笔鸡舍订单订单去支付
     *
     * @param token
     * @param vo
     * @return
     */
    public RestResponse handlePayChickenOrder(String token, FarmOrderPayVo vo) {
        if (vo.getPayType() == null) {
            return GetRest.getFail("请选择支付方式");
        }

        if (vo.getOrderType() != OrderTypeEnums.SELL.getId() && vo.getOrderType() != OrderTypeEnums.ADOPTION.getId()) {
            return GetRest.getFail("请选择订单类型");
        }
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), vo.getPayType())) {
            if (StringUtils.isBlank(vo.getPayWord())) {
                return GetRest.getFail("请填写交易密码");
            }
        }

        //1.校验用户信息
        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        CCustomer cCustomer = icCustomerService.getById(dto.getCid());
        if (cCustomer == null) {
            return GetRest.getFail("用户不存在或被冻结");
        } else if (calcuUtils.isEquals(StaticUtils.STATUS_NO, cCustomer.getStatus())) {
            String desc = icCustomerService.checkFrezeeCustomer(UserFreezeEnums.CUSTOMER_PAY.getId(), vo.getPayType());
            if (desc.length() > 0) {
                return GetRest.getFail(desc);
            }
        }

        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), vo.getPayType())) {
            if (StringUtils.isEmpty(cCustomer.getPayWord())) {
                return GetRest.getFail("您还未设置支付密码,请前往设置~", null, "1");
            }
            String pwd = Encode.md5Encode(vo.getPayWord());
            if (!pwd.equals(cCustomer.getPayWord())) {
                return GetRest.getFail("支付密码不正确");
            }

            if (!calcuUtils.isEquals(cCustomer.getAuthen(), StaticUtils.STATUS_YES)) {
                return GetRest.getFail("请先进行身份认证", null, "2");
            } else {
                QueryWrapper<CCustomerAuthen> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("cid", dto.getCid());
                CCustomerAuthen authen = customerAuthenService.getOne(queryWrapper);
                if (authen == null) {
                    return GetRest.getFail("请求错误，错误代码0000");
                }
            }
        }
        ChickenLevel chickenLevelInfo = iChickenLevelService.getById(vo.getCrId());

        //判断会员等级是否有购买套餐3的权利

        if (calcuUtils.isEquals(StaticUtils.FARM_3, chickenLevelInfo.getLevel())
                && !calcuUtils.isEquals(cCustomer.getLevelid(), CustomerLevelEnums.LARGE.getId())) {
            return GetRest.getFail("只有等级为大型养殖户才能购买!");
        }

        //判断二号鸡舍的直推人数是否达到
        if (calcuUtils.isEquals(chickenLevelInfo.getLevel(), StaticUtils.FARM_2)) {
            QueryWrapper<CCustomer> wrapper = new QueryWrapper<>();
            wrapper.eq("parentid", cCustomer.getId()).eq("levelid", CustomerLevelEnums.BREEDER.getId());
            int count = icCustomerService.count(wrapper);
            if (count < 2) {
                return GetRest.getFail("伞下直推未到达要求，无法购买鸡舍!");
            }
        }

        //份数
        Integer qty = 0;
        if (vo.getQty() % chickenLevelInfo.getQty() != 0) {
            return GetRest.getFail("购买的数量不符合要求");
        } else {
            qty = vo.getQty() / chickenLevelInfo.getQty();
        }

        if (qty > chickenLevelInfo.getTotalQty() - chickenLevelInfo.getSaleQty()) {
            return GetRest.getFail("已超过可认购量!");
        }

        BigDecimal totalPayMoney = calcuUtils.mul(chickenLevelInfo.getTotalPrice(), new BigDecimal(qty), 2); //需要支付金额
        BigDecimal totalFraction = calcuUtils.mul(chickenLevelInfo.getFraction(), new BigDecimal(qty), 2); //需要创业分

        //进入下单流程
        String payCode = CalcuUtils.getInstance().getOrderCode("COP");
        CAccount account = icAccountService.selectByCid(cCustomer.getId());
        if (account.getPoint().compareTo(totalFraction) < 0) {
            throw new ThrowJsonException("您的创业分不足，无法进行购买");
        }

        if (calcuUtils.isEquals(vo.getPayType(), PayTypeEnums.PAY_MONEY.getId())) {
            if (account.getMoney().compareTo(totalPayMoney) < 0) {
                throw new ThrowJsonException("您的余额不足，无法进行购买");
            }
            if (totalPayMoney.compareTo(BigDecimal.ZERO) < 0) {
                throw new ThrowJsonException("支付金额不能小于0，无法进行购买");
            }
        }

        int ocount = chickenOrderMapper.selectByCidAndType(cCustomer.getId(), chickenLevelInfo.getId());//鸡舍数据行数
        //得到一个NumberFormat的实例
        NumberFormat nf = NumberFormat.getInstance();
        //设置是否使用分组
        nf.setGroupingUsed(false);
        //设置最大整数位数
        nf.setMaximumIntegerDigits(4);
        //设置最小整数位数
        nf.setMinimumIntegerDigits(4);
        String number = nf.format(ocount + 1);
        //生成订单
        ChickenOrder chickenOrder = new ChickenOrder();
        chickenOrder.setPayCode(payCode);
        chickenOrder.setPayType(vo.getPayType());
        chickenOrder.setFromChannel(vo.getFromChannel());
        chickenOrder.setPayChannel(vo.getPayChannel());
        chickenOrder.setCid(cCustomer.getId());
        chickenOrder.setOrderCode(CalcuUtils.getInstance().getOrderCode("CO"));
        chickenOrder.setOrderType(vo.getOrderType());
        chickenOrder.setPrice(chickenLevelInfo.getPrice());
        chickenOrder.setSalePrice(chickenLevelInfo.getSalePrice());
        chickenOrder.setCrId(vo.getCrId());
        chickenOrder.setBuyNum(vo.getQty());
        chickenOrder.setPayMoney(totalPayMoney);
        chickenOrder.setPoint(totalFraction);
        chickenOrder.setNumber(number);//鸡舍订单序号
        iChickenOrderService.save(chickenOrder);
        //生成支付记录
        CPayLog log = new CPayLog();
        log.setCid(dto.getCid());
        log.setPayCode(payCode);
        log.setPayMoney(totalPayMoney);
        log.setPoint(totalFraction);
        log.setServiceType(ServiceEnums.FARM_ORDER.getId());
        log.setPayChannel(vo.getPayChannel());
        log.setPayType(vo.getPayType());
        if (calcuUtils.isEquals(PayChannlEnums.WX_PUBLIC.getId(), vo.getPayChannel())) {
            if (StringUtils.isEmpty(cCustomer.getOpenidWx())) {
                throw new ThrowJsonException("OPENID IS NULL");
            }
            log.setOpenId(cCustomer.getOpenidWx());
        } else {
            if (calcuUtils.isEquals(PayChannlEnums.WX_PROGRAM.getId(), vo.getPayChannel())) {
                if (StringUtils.isEmpty(cCustomer.getOpenidProgram())) {
                    throw new ThrowJsonException("OPENID IS NULL");
                }
                log.setOpenId(cCustomer.getOpenidProgram());
            }
        }
        boolean flag = icPayLogService.save(log);
        if (!flag) {
            throw new ThrowJsonException("生成支付记录失败");
        }
        //支付记录存在之后开始处理订单签名
        return payService.handleSign(log);

    }

    /**
     * 处理单笔物流提鸡订单去支付
     *
     * @param token
     * @param vo
     * @return
     */
    public RestResponse handlePayChickenLogisticsOrder(String token, FarmLogisticsOrderPayVo vo) {
        if (vo.getPayType() == null) {
            return GetRest.getFail("请选择支付方式");
        }
        if (vo.getCouponId() == null) {
            return GetRest.getFail("请选择一张提鸡券");
        }
        if (vo.getAddrId() == null) {
            return GetRest.getFail("请选择收货地址");
        }

        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), vo.getPayType())) {
            if (StringUtils.isBlank(vo.getPayWord())) {
                return GetRest.getFail("请填写交易密码");
            }
        }

        //1.校验用户信息
        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        CCustomer cCustomer = icCustomerService.getById(dto.getCid());
        if (cCustomer == null) {
            return GetRest.getFail("用户不存在或被冻结");
        } else if (calcuUtils.isEquals(StaticUtils.STATUS_NO, cCustomer.getStatus())) {
            String desc = icCustomerService.checkFrezeeCustomer(UserFreezeEnums.CUSTOMER_PAY.getId(), vo.getPayType());
            if (desc.length() > 0) {
                return GetRest.getFail(desc);
            }
        }

        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), vo.getPayType())) {
            if (StringUtils.isEmpty(cCustomer.getPayWord())) {
                return GetRest.getFail("您还未设置支付密码,请前往设置~", null, "1");
            }
            String pwd = Encode.md5Encode(vo.getPayWord());
            if (!pwd.equals(cCustomer.getPayWord())) {
                return GetRest.getFail("支付密码不正确");
            }

            if (!calcuUtils.isEquals(cCustomer.getAuthen(), StaticUtils.STATUS_YES)) {
                return GetRest.getFail("请先进行身份认证", null, "2");
            } else {
                QueryWrapper<CCustomerAuthen> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("cid", dto.getCid());
                CCustomerAuthen authen = customerAuthenService.getOne(queryWrapper);
                if (authen == null) {
                    return GetRest.getFail("请求错误，错误代码0000");
                }
            }
        }
        ChickenCoupon chickenCoupon = iChickenCouponService.getById(vo.getCouponId());
        if (!calcuUtils.isEquals(chickenCoupon.getCid(), cCustomer.getId())
                || !calcuUtils.isEquals(chickenCoupon.getStatus(), ChickenCouponStatusEnums.WAITUSE.getId())) {
            return GetRest.getFail("该提鸡券无效，请重新选择");
        }
        //获取运费
        CReceivedAddr cReceivedAddr = cReceivedAddrMapper.selectById(vo.getAddrId());
        BigDecimal exp = expService.getExpByFarm(cReceivedAddr);

        //进入下单流程
        String payCode = CalcuUtils.getInstance().getOrderCode("COP");

        if (exp.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ThrowJsonException("自营商家还未开放物流提鸡哦，请耐心等待");
        }
        //找自营店铺
        BExpConfig config = ibExpConfigService.selectChickenExpConfig();

        if (config == null) {
            throw new ThrowJsonException("还未开放物流提鸡哦，请耐心等待");
        }
        //更新提鸡券状态
        chickenCoupon.setStatus(ChickenCouponStatusEnums.USED.getId());
        chickenCoupon.setUseType(ChickenCouponUseTypeEnums.LOGISTICS.getId());
        iChickenCouponService.updateById(chickenCoupon);

        //处理生成订单信息
        String orderCode = CalcuUtils.getInstance().getOrderCode("O");
        OrderMain orderMain = new OrderMain();
        orderMain.setCid(cCustomer.getId());
        orderMain.setBid(config.getBid());
        orderMain.setBType(BusinessTypeEnums.OWN_BUSINESS.getId());
        orderMain.setPayCode(payCode);
        orderMain.setOrderCode(orderCode);
        orderMain.setTotalNum(1);
        orderMain.setGoodsMoney(BigDecimal.ZERO);
        orderMain.setRealMoney(BigDecimal.ZERO);
        orderMain.setExpMoney(exp);
        orderMain.setPayMoney(exp);
        orderMain.setDiscountMoney(BigDecimal.ZERO);
        orderMain.setCouponMoney(BigDecimal.ZERO);
        orderMain.setOtherMoney(BigDecimal.ZERO);
        orderMain.setPoint(BigDecimal.ZERO);
        orderMain.setOrderType(OrderTypeEnums.LOGISTICS.getId());
        orderMain.setOrderStatus(OrderStatusEnums.COMFIRE.getId());
        orderMain.setPayType(vo.getPayType());
        orderMain.setCouponId(vo.getCouponId());
        //计算支付截止时间
        QueryWrapper<InfoShopping> wrapper = new QueryWrapper<>();
        InfoShopping infoShopping = iInfoShoppingService.getOne(wrapper);
        Date confirmTime = DateUtil.getInstance().currentDate();
        orderMain.setConfirmTime(confirmTime);
        Date payEndTime = DateUtil.getInstance().addMinute(confirmTime, infoShopping.getAutoCancel());
        orderMain.setPayendTime(payEndTime);
        orderMain.setRemark("");
        orderMain.setFromChannel(vo.getFromChannel());
        orderMain.setPayChannel(vo.getPayChannel());
        //保存订单信息
        boolean flag = iOrderMainService.save(orderMain);
        if (!flag) {
            throw new ThrowJsonException("订单生成失败CODE:1001");
        }
        //保存发货单
        if (cReceivedAddr != null) {
            OrderExpDetail expDetail = new OrderExpDetail();
            expDetail.setBid(orderMain.getBid());
            expDetail.setCid(cCustomer.getId());
            expDetail.setBType(orderMain.getBType());
            expDetail.setOrderCode(orderCode);
            expDetail.setDetailIds(String.valueOf(vo.getCouponId()));
            expDetail.setAddrids(cReceivedAddr.getProId() + "," + cReceivedAddr.getCityId() + "," + cReceivedAddr.getAreaId());
            expDetail.setAddressDetail(cReceivedAddr.getAddress());
            expDetail.setAddrPrefix(cReceivedAddr.getNameExt());
            expDetail.setReceiver(cReceivedAddr.getName());
            expDetail.setPhone(cReceivedAddr.getPhone());
            iOrderExpDetailService.save(expDetail);
        }

        //生成支付记录
        CPayLog log = new CPayLog();
        log.setCid(dto.getCid());
        log.setPayCode(payCode);
        log.setPayMoney(exp);
        log.setPoint(BigDecimal.ZERO);
        log.setServiceType(ServiceEnums.FARM_LOGISTICS_ORDER.getId());
        log.setPayChannel(vo.getPayChannel());
        log.setPayType(vo.getPayType());
        if (calcuUtils.isEquals(PayChannlEnums.WX_PUBLIC.getId(), vo.getPayChannel())) {
            if (StringUtils.isEmpty(cCustomer.getOpenidWx())) {
                throw new ThrowJsonException("OPENID IS NULL");
            }
            log.setOpenId(cCustomer.getOpenidWx());
        } else {
            if (calcuUtils.isEquals(PayChannlEnums.WX_PROGRAM.getId(), vo.getPayChannel())) {
                if (StringUtils.isEmpty(cCustomer.getOpenidProgram())) {
                    throw new ThrowJsonException("OPENID IS NULL");
                }
                log.setOpenId(cCustomer.getOpenidProgram());
            }
        }
        flag = icPayLogService.save(log);
        if (!flag) {
            throw new ThrowJsonException("生成支付记录失败");
        }
        //支付记录存在之后开始处理订单签名
        return payService.handleSign(log);

    }

    /**
     * 重新发起支付
     *
     * @param token
     * @param orderCode
     * @param payChannel 支付渠道 件枚举类PayChannlEnums
     * @return
     */
    public RestResponse handleAgain(String token, String orderCode, Integer payChannel) {
        String result = redisUtilsService.getKey(RedisExpiredEnums.ORDER_BUY.getKey() + orderCode);
        if (StringUtils.isEmpty(result)) {
            return GetRest.getFail("订单已超过支付有效期");
        }
        SettleDto settleDto = JSONObject.parseObject(result, SettleDto.class);

        LoginDto dto = loginTokenService.validLoginLoginDto(token);
        CCustomer cCustomer = icCustomerService.getById(dto.getCid());
        if (cCustomer == null) {
            return GetRest.getFail("用户不存在");
        }

        OrderMain main = iOrderMainService.getByOrderCode(orderCode);
        if (main == null || !CalcuUtils.getInstance().isEquals(OrderStatusEnums.COMFIRE.getId(), main.getOrderStatus())) {
            return GetRest.getFail("订单已超过支付有效期");
        }
        if (!CalcuUtils.getInstance().isEquals(main.getCid(), dto.getCid())) {
            return GetRest.getFail("非本人操作");
        }

        //余额支付需要判断是否绑定银行卡
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        if (calcuUtils.isEquals(PayTypeEnums.PAY_MONEY.getId(), main.getPayType())) {
            if (!calcuUtils.isEquals(cCustomer.getAuthen(), StaticUtils.STATUS_YES)) {
                return GetRest.getFail("请先进行身份认证", null, "2");
            } else {
                QueryWrapper<CCustomerAuthen> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("cid", dto.getCid());
                CCustomerAuthen authen = customerAuthenService.getOne(queryWrapper);
                if (authen == null) {
                    return GetRest.getFail("请求错误，错误代码0000");
                } else if (StringUtils.isBlank(authen.getBankCard())) {
                    //验证银行卡是否绑定
                    int count = bankDetailMapper.countBankDetailByTargetId(dto.getCid());
                    if (count == 0) {
                        return GetRest.getFail("请先绑定银行卡");
                    }
                }
            }
        }

        //用户冻结
        if (CalcuUtils.getInstance().isEquals(StaticUtils.STATUS_NO, cCustomer.getStatus())) {
            String desc = icCustomerService.checkFrezeeCustomer(UserFreezeEnums.CUSTOMER_PAY.getId(), main.getPayType());
            if (desc.length() > 0) {
                return GetRest.getFail(desc);
            }
        }

        //重新生成支付信息
        //修改订单支付信息
        String payCode = CalcuUtils.getInstance().getOrderCode("A");
        main.setPayCode(payCode);
        iOrderMainService.updateById(main);

        CPayLog log = new CPayLog();
        log.setCid(dto.getCid());
        log.setPayCode(payCode);
        log.setPayMoney(main.getPayMoney());
        log.setServiceType(ServiceEnums.ORDER.getId());
        log.setPayChannel(payChannel);
        log.setPayType(main.getPayType());
        if (CalcuUtils.getInstance().isEquals(PayChannlEnums.WX_PUBLIC.getId(), payChannel)) {
            if (StringUtils.isEmpty(cCustomer.getOpenidWx())) {
                throw new ThrowJsonException("OPENID IS NULL");
            }
            log.setOpenId(cCustomer.getOpenidWx());
        } else {
            if (CalcuUtils.getInstance().isEquals(PayChannlEnums.WX_PROGRAM.getId(), payChannel)) {
                if (StringUtils.isEmpty(cCustomer.getOpenidProgram())) {
                    throw new ThrowJsonException("OPENID IS NULL");
                }
                log.setOpenId(cCustomer.getOpenidProgram());
            }
        }
        boolean flag = icPayLogService.save(log);
        if (!flag) {
            throw new ThrowJsonException("生成支付记录失败");
        }
        //支付记录存在之后开始处理订单签名
        return payService.handleSign(log);
    }

    /**
     * 处理单笔去支付
     *
     * @param payCode     交易单号
     * @param token
     * @param payWord     支付密码
     * @param payType     支付方式
     * @param remark      订单备注
     * @param fromChannel 订单来源渠道
     * @return 保存订单信息 并返回支付金额
     */
    public BigDecimal handleSingleOrderPay(SettleDto settleDto, Integer cid, String payCode, String token,
                                           String payWord, Integer payType, String remark, Integer fromChannel, Integer payChannel) {
        CalcuUtils calcuUtils = CalcuUtils.getInstance();
        //处理生成订单信息
        String orderCode = calcuUtils.getOrderCode("O");
        OrderMain orderMain = new OrderMain();
        orderMain.setCid(cid);
        orderMain.setBid(settleDto.getBid());
        orderMain.setBType(settleDto.getBType());
        orderMain.setPayCode(payCode);
        orderMain.setOrderCode(orderCode);
        orderMain.setTotalNum(settleDto.getTotalNum());
        orderMain.setGoodsMoney(settleDto.getGoodsMoney());
        orderMain.setRealMoney(settleDto.getRealMoney());
        orderMain.setExpMoney(settleDto.getExpMoney());
        orderMain.setPayMoney(settleDto.getPayMoney());
        orderMain.setDiscountMoney(settleDto.getDiscountMoney());
        orderMain.setCouponMoney(settleDto.getCouponMoney());
        orderMain.setOtherMoney(settleDto.getOtherMoney());
        orderMain.setPoint(settleDto.getPoint());
        orderMain.setOrderType(settleDto.getOrderType());
        orderMain.setLabel(settleDto.getLabel());
        orderMain.setOrderStatus(OrderStatusEnums.COMFIRE.getId());
        orderMain.setPayType(payType);
        //线下订单生成核销码
        if (calcuUtils.isEquals(settleDto.getOrderType(), OrderTypeEnums.OFFLINE.getId())) {
            RestUploadFileInfo uploadQr = new UploadUtils().uploadQr(orderCode);
            if (uploadQr.isStatus()) {
                orderMain.setVerifyCode(uploadQr.getData());
            }
        }

        //计算支付截止时间
        QueryWrapper<InfoShopping> wrapper = new QueryWrapper<>();
        InfoShopping infoShopping = iInfoShoppingService.getOne(wrapper);
        Date confirmTime = DateUtil.getInstance().currentDate();
        orderMain.setConfirmTime(confirmTime);
        Date payEndTime = DateUtil.getInstance().addMinute(confirmTime, infoShopping.getAutoCancel());
        orderMain.setPayendTime(payEndTime);
        orderMain.setRemark(remark);
        orderMain.setFromChannel(fromChannel);
        orderMain.setPayChannel(payChannel);
        //保存订单信息
        boolean flag = iOrderMainService.save(orderMain);
        if (!flag) {
            throw new ThrowJsonException("订单生成失败CODE:1001");
        }
        //保存发货单
        CReceivedAddr addr = settleDto.getReceivedAddr();
        List<SettleDetailDto> detailDtos = settleDto.getDetailDtos();
        Map<String, String> map = new HashMap<>();
        for (SettleDetailDto d : detailDtos) {
            //获取仓库id
            Integer wid = null;
            if (addr != null) {
                wid = iwWarehouseService.selectWarehouseIdByAddr(addr.getId(), d.getProcode(), d.getSkuid(), d.getQty());
            }
            if (wid == null) {
                wid = -1;
            }
            String mKey = String.valueOf(wid);
            String mVal = map.get(mKey);
            if (!StringUtils.isEmpty(mVal)) {
                map.put(mKey, mVal + "," + d.getSkuid());
            } else {
                map.put(mKey, String.valueOf(d.getSkuid()));
            }
            OrderDetail detail = new OrderDetail();
            detail.setOrderCode(orderCode);
            detail.setProId(d.getPid());
            detail.setProCode(d.getProcode());
            detail.setProDetailId(d.getSkuid());
            detail.setProName(d.getPname());
            detail.setProSpecName(d.getSkuname());
            detail.setProUrl(d.getPurl());
            detail.setProUnit(d.getUnit());
            detail.setQty(d.getQty());
            detail.setWeight(d.getWeight());
            detail.setPrice(d.getPrice());
            detail.setGoodMoney(d.getGoodmoney());
            detail.setDiscountMoney(d.getDiscountMoney());
            detail.setCouponMoney(d.getCouponMoney());
            detail.setOtherMoney(d.getOtherMoney());
            detail.setPoint(d.getPoint());
            detail.setLabel(d.getLabel());
            detail.setActivitySign(d.getActivitySign());
            detail.setProType(d.getProType());
            detail.setCostPrice(d.getCostPrice());
            detail.setIsRefund(d.getRefundFlag());
            //处理扣除库存 如果不是秒杀库存 商品库存 如果是秒杀增加秒杀已售库存
            ProSkuDetail sku = iProSkuDetailService.getById(d.getSkuid());
            sku.setId(d.getSkuid());
            sku.setOperationType(OperationTypeEnums.SUB_QTY.getId());
            sku.setQty(d.getQty());
            int op = iProSkuDetailService.updateQtyVersion(sku);
            if (op < 1) {
                throw new ThrowJsonException("商品【" + d.getPname() + "】库存不足~");
            }
//            }
            //保存订单明细表
            boolean dFlag = iOrderDetailService.save(detail);
            if (!dFlag) {
                throw new ThrowJsonException("订单生成失败CODE:1002");
            }
        }
        //将订单号保存到实体
        settleDto.setCid(cid);
        settleDto.setOrdercode(orderCode);

        //保存发货单同一个仓库为一个发货单
        if (addr != null) {
            for (String w : map.keySet()) {
                Integer wid = Integer.parseInt(w);
                if ("-1".equals(w)) {
                    wid = null;
                }
                String detailIds = map.get(w);
                OrderExpDetail expDetail = new OrderExpDetail();
                expDetail.setBid(orderMain.getBid());
                expDetail.setWid(wid);
                expDetail.setCid(cid);
                expDetail.setDetailIds(detailIds);
                expDetail.setBType(orderMain.getBType());
                expDetail.setOrderCode(orderCode);
                expDetail.setAddrids(addr.getProId() + "," + addr.getCityId() + "," + addr.getAreaId());
                expDetail.setAddressDetail(addr.getAddress());
                expDetail.setAddrPrefix(addr.getNameExt());
                expDetail.setReceiver(addr.getName());
                expDetail.setPhone(addr.getPhone());
                iOrderExpDetailService.save(expDetail);
            }
        }
        redisUtilsService.setKey(RedisExpiredEnums.ORDER_BUY.getKey() + orderCode, JSONObject.toJSONString(settleDto), RedisExpiredEnums.ORDER_BUY.getSecond());
        return settleDto.getPayMoney();
    }

}
